#include <string>
#include <apr_base64.h>
#include <iostream>

#include <apr_queue.h>
#include <apr_thread_pool.h>
#include <apr_network_io.h>
#include <log4cxx/logger.h>
#include <log4cxx/propertyconfigurator.h>

#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>






#include "dbs.h"
using namespace std;
using namespace log4cxx;


extern LoggerPtr gLogger;
static db_pool dbs;//数据库池


bool base64_encode(string& str)
{
    char buf[1024];
    int nNew = apr_base64_encode(buf, str.c_str(), str.length());
    buf[nNew] = 0;
    str = buf;
    return nNew > 0;
}
bool base64_decode(string& str)
{
    char buf[1024];
    int nDe = apr_base64_decode(buf, str.c_str());
    buf[nDe] = 0;
    str = buf;
    return nDe > 0;
}

bool initDBS(CIniFile& config, char* database, apr_pool_t* pool)
{

    int nPool = config.GetValueI(database, "pool", 10);

    const string strServer = config.GetValue(database, "uri", "");
    const string username = config.GetValue(database, "user", "");
    const string passwd  = config.GetValue(database, "pwd", "");
    const string schema  = config.GetValue(database, "schema", "");

    if (nPool <= 0
            || (strServer.empty())
            || (username.empty())
            || (passwd.empty())
            || (schema.empty()))
    {
        LOG4CXX_WARN(gLogger, "database config error!");
    }

    if (!dbs.init(nPool, strServer, username, passwd, schema, pool))
    {
        LOG4CXX_WARN(gLogger, "Create Read DataBases ERR");
        return false;
    }

    return true;
}

void destoryDBS()
{
    dbs.destory();
}
sql::Connection * db_pool::init_DBC()
{
    try
    {
        sql::ConnectOptionsMap connection_properties;

        connection_properties["hostName"] = m_strUri;
        connection_properties["userName"] = m_strUid;
        connection_properties["password"] = m_strPwd;
        connection_properties.erase("CLIENT_MULTI_RESULTS");
        connection_properties["CLIENT_MULTI_RESULTS"] = true;

        sql::Driver * driver = get_driver_instance();
        sql::Connection *con;
        auto_ptr<sql::Statement> stmt;
        auto_ptr<sql::ResultSet> res;

        con = driver->connect(connection_properties);
        //con -> setAutoCommit(0);
        con -> setSchema(m_strSchema);
        stmt.reset(con->createStatement());
        res.reset(stmt->executeQuery("SELECT 'test server!' AS _message"));

        while (res->next())
        {
            res->getString("_message");
        }

        return con;
    }
    catch (sql::SQLException &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what() << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
        return NULL;
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );

        return NULL;
    }
}
bool db_pool::init(int nPools, const string& strServer, const string& strUid, const string& strPwd, const string& schema, apr_pool_t* pool)
{
    m_nPools = nPools;
    m_strUri = strServer;
    m_strUid = strUid;
    m_strPwd = strPwd;
    m_strSchema = schema;

    m_pool = pool;

    if (apr_queue_create(&m_dbs, m_nPools*2, pool) != APR_SUCCESS)
    {
        LOG4CXX_WARN(gLogger, "Create DataBase queue ERR");
        return false;
    }

    for (unsigned int i = 0; i < m_nPools; i++)
    {
        sql::Connection* con = init_DBC();

        if (con != NULL)
        {
            apr_queue_push(m_dbs, con);
        }
    }


    if (apr_queue_size(m_dbs) == 0)
    {
        apr_queue_term(m_dbs);
        LOG4CXX_WARN(gLogger, "Connect DataBase ERR failed");
        return false;
    }

    return true;
}




void db_pool::destory()
{
    apr_queue_interrupt_all(m_dbs);
    void* pData = NULL;
    apr_status_t rv = APR_SUCCESS;

    do
    {
        rv = apr_queue_trypop(m_dbs, &pData);

        if (rv == APR_SUCCESS)
        {
            sql::Connection* pConn = (sql::Connection*)pData;

            try
            {
                pConn->close();
                delete pConn;
            }
            catch (sql::SQLException &e)
            {
                LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                             << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
            }
            catch (std::runtime_error &e)
            {
                LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                             << "\r\bERROR: " << e.what() );

            }

            pData = NULL;
        }
    }
    while (rv != APR_EAGAIN);
}

sql::Connection* db_pool::GetDBC()
{
    sql::Connection* pConn = NULL;
    void* pData = NULL;

    if (apr_queue_trypop(m_dbs, &pData) != APR_SUCCESS)
    {
        pConn = init_DBC();
    }
    else
    {
        pConn = (sql::Connection*)pData;
    }

    try
    {
        auto_ptr<sql::Statement> stmt;
        auto_ptr<sql::ResultSet> res;

        stmt.reset(pConn->createStatement());
        res.reset(stmt->executeQuery("SELECT 'test server!' AS _message"));

        while (res->next())
        {
            res->getString("_message");
        }
    }
    catch (sql::SQLException &e)
    {
        delete pConn;
        pConn = NULL;
        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        delete pConn;
        pConn = NULL;
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    return pConn;
}

void db_pool::ReleaseDBC(sql::Connection* pConn)
{
    if (apr_queue_size(m_dbs) < ( unsigned int )m_nPools)
    {
        if (apr_queue_trypush(m_dbs, pConn) == APR_SUCCESS)
        {
            return;
        }
    }

    delete pConn;
}

sql::Connection * GetDBC()
{
    return dbs.GetDBC();
}

void ReleaseDBC(sql::Connection* pConn)
{
    dbs.ReleaseDBC(pConn);
}


bool getCallParam(const string& acc, const string& caller, const string& called, CALL_TYPE calltype, vector<call_param_t>& callParams)
{
    sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }

    try
    {

        std::auto_ptr< sql::ResultSet > res;

        stringstream strstmt;

        switch (calltype)
        {
        case VOIP:
        case DIRECT:
	    LOG4CXX_WARN(gLogger,"CALL callback(\"" << acc << "\",\"" << caller << "\",\"" << called << "\"," << (int)calltype << ")");
	    strstmt << "CALL callback(\"" << acc << "\",\"" << caller << "\",\"" << called << "\"," << (int)calltype << ")";
            break;
        case GATEWAY:
        case AUTHCALL:
            strstmt << "CALL voip(\"" << acc << "\",\"" << caller << "\",\"" << called << "\"," << (int)calltype << ")";
            break;
        case CALLBACK1:
		strstmt << "CALL callback(\"" << acc << "\",\"" << caller << "\",\"" << called << "\"," << (int)calltype << ")";
            break;
        case CALLBACK2:
            strstmt << "CALL callback(\"" << acc << "\",\"" << caller << "\",\"" << called << "\"," << (int)calltype << ")";
            break;
        case CONFERENCE:
            strstmt << "CALL conference(\"" << acc << "\",\"" << caller << "\",\"" << called << "\"," << (int)calltype << ")";
            break;
        default:
            LOG4CXX_WARN(gLogger, "ERROR call type =" << (int)calltype);
            dbs.ReleaseDBC(pConn);
            return false;
        }
		LOG4CXX_INFO(gLogger,strstmt.str());
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(strstmt.str());

        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
                call_param_t param;
                /*string codec;
                int    bRingFlag;
                string server;
                int    nTimeout;
                string caller;
                string called;
                */
                //语音编码,透传彩铃标志，落地，最大时长，外呼主叫，外呼被叫
                param.codec = res->getString(1);
                param.bRingFlag = res->getInt(2);
                param.server = res->getString(3);
                param.nTimeout = res->getInt(4);
                param.caller = res->getString(5);
                param.called = res->getString(6);
                callParams.push_back(param);
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }

    return !callParams.empty();
}


/*
四、计费存储过程：
1.传入参数：呼叫类型，计费账号，主叫，被叫，落地，呼叫起始时间，呼叫终止时间，呼叫时长
其中： 呼叫类型：1表示回拨第一路，2表示回拨第二路，3表示VOIP呼叫，4表示直拨，5表示接入，6表示会议呼叫
计费账号：计费的账号
主叫：    本路呼叫的主叫
被叫：    本路呼叫的被叫
落地：    本次呼叫使用的落地
呼叫起始时间：呼叫发起的时间
呼叫终止时间：呼叫结束的时间
呼叫时长：    本次呼叫接通的时间
2.返回参数：无
enum CALL_TYPE
{
CALLBACK1 = 1,
CALLBACK2 = 2,
VOIP = 3,
DIRECT = 4,
GATEWAY = 5,
MEETME = 6
};
*/
bool bill(CALL_TYPE calltype, const char* acc, const char* caller, const char* called, const char* server, const char* startTime, const char* endTime, int nCallTime)
{
    bool bBill = false;
    bool bConnErr = false;
    sql::Connection* pConn = dbs.GetDBC();

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        LOG4CXX_ERROR(gLogger, "calltype=" << (int)calltype << ",\tacc=" << acc
                      << ",\tcaller=" << caller << ",\tcalled" << called << ",\tserver=" << server
                      << ",\tstartTime=" << endTime << ",\tnCallTime=" << nCallTime);
        return false;
    }

    try
    {
//        std::auto_ptr< sql::PreparedStatement >  pstmt;
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "CALL bill("<<(int)calltype<<",'"<< acc << "','" << caller<< "','"<<called<<"','"<<server<< "','" <<
           startTime<< "','" <<endTime<< "'," <<nCallTime<<")";

        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());
       
        /*
        		string strstmt = "CALL bill(?,?,?,?,?,?,?,?)";
                pstmt.reset(pConn->prepareStatement(strstmt));

                pstmt->setInt(1, (int)calltype);
                pstmt->setString(2, acc);
                pstmt->setString(3, caller);
                pstmt->setString(4, called);
                pstmt->setString(5, server);
                pstmt->setString(6, startTime);
                pstmt->setString(7, endTime);
                pstmt->setInt(8, nCallTime);
                pstmt->execute();
        */
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
            }
        }
        while (stmt->getMoreResults());

        bBill = true;
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }

    return bBill;
}

bool insertCallback(string& acct, string& caller, string& called)
{
    sql::Connection *con = GetDBC();

    try
    {
        if (con != NULL)
        {
            LOG4CXX_INFO(gLogger, "insert get database connect  success");
        }
        else
        {
            LOG4CXX_WARN(gLogger, "insert get database connect  failed");
            return -1;
        }

        std::auto_ptr<sql::Statement> stmt ( con->createStatement());
        std::auto_ptr< sql::ResultSet > res;
        stmt->execute(("INSERT into ordercall (acct,caller,called) VALUES(\"" + acct + "\",\"" + caller + "\",\"" + called + "\")").c_str());
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
            }
        }
        while (stmt->getMoreResults());

        ReleaseDBC(con);
    }
    catch (sql::SQLException &e)
    {
        delete con;
        LOG4CXX_WARN(gLogger, "err:" << e.what() << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState());
    }

    return 0;
}
bool insertAuth(string& acct, string& caller)
{
	sql::Connection *con = GetDBC();

	try
	{
		if (con != NULL)
		{
			LOG4CXX_INFO(gLogger, "insert get database connect  success");
		}
		else
		{
			LOG4CXX_WARN(gLogger, "insert get database connect  failed");
			return -1;
		}

		std::auto_ptr<sql::Statement> stmt ( con->createStatement());
		std::auto_ptr< sql::ResultSet > res;
		stmt->execute(("INSERT into orderauth (acct,caller,authcode) VALUES(\"" + acct + "\",\"" + caller + "\",SUBSTRING(CONCAT(rand(now())),3,4))").c_str());
		do
		{
			res.reset(stmt->getResultSet());

			while ((res.get() != NULL) && res->next())
			{
			}
		}
		while (stmt->getMoreResults());

		ReleaseDBC(con);
	}
	catch (sql::SQLException &e)
	{
		delete con;
		LOG4CXX_WARN(gLogger, "err:" << e.what() << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState());
	}

	return 0;
}

//VIP操作 0=开 1=关
bool vippay(const string& acctname,int flag)
{
	sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }

    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call acct_vippay("<< acctname << "," << flag << ")";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());
		LOG4CXX_WARN(gLogger,"sql = " << ss.str());
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
				//flag = res->getString(1);
                //acctname = res->getString(1);
				LOG4CXX_WARN(gLogger,"acct_vippay OK:" << acctname);
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }
	//1 ok 
	return true;

}


//绑定回拨亲亲号
bool bindcbnum(const string& acctname, string& bindnum, string& sipnum)
{
	sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;
    string flag = "-1";

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }
    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call acct_cbbindnum(\'"<< acctname << "\',\'" << bindnum << "\',\'" << sipnum <<"\')";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());
		LOG4CXX_WARN(gLogger,"sql = " << ss.str());
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
				flag = res->getString(1);
                //acctname = res->getString(1);
				LOG4CXX_WARN(gLogger,"acct_cbbindnum = " << res->getString(1));
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }
	//1 ok 
	return strcmp(flag.c_str(), "1") == 0;

}

//查询是否存在账号
bool isExitUser(const string& acctname,string& idstr)
{
    sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;
     idstr = "0";

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }

    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call user_exit(\'" << acctname << "\')";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());
		LOG4CXX_WARN(gLogger,"sql = " << ss.str());
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
                idstr = res->getString(1);
				LOG4CXX_WARN(gLogger,"id = " << idstr);
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }

    return strlen(idstr.c_str()) > 1;
}


//查询回拨快捷号码
bool getcbnum(const string& acctname,string& sipnum,string& quicknum)
{
    sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;
    quicknum = "0";

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }

    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call acct_getcbnum(\'" << acctname << "\',\'" << sipnum << "\')";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());
		LOG4CXX_WARN(gLogger,"sql = " << ss.str());
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
                quicknum = res->getString(1);
				LOG4CXX_WARN(gLogger,"cbnum = " << quicknum);
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }

    return strlen(quicknum.c_str()) > 1;
}


//绑定亲亲号
bool bindqinqin(const string& acctname,string& bindnum,string& sipnum)
{
	sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;
    string flag = "-1";

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }
    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call bind_quicknum(\'"<< acctname << "\',\'" << bindnum << "\',\'" << sipnum <<"\')";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());
		LOG4CXX_WARN(gLogger,"sql = " << ss.str());
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
				flag = res->getString(1);
                //acctname = res->getString(1);
				LOG4CXX_WARN(gLogger,"bind_quicknum = " << res->getString(1));
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }
	//1 ok 
	return strcmp(flag.c_str(), "1") == 0;

}

//查询亲亲快捷号码
bool getquicknum(const string& acctname,string& sipnum,string& quicknum)
{
    sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;
    quicknum = "0";

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }

    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call acct_getquicknum(\'" << acctname << "\',\'" << sipnum << "\')";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());
		LOG4CXX_WARN(gLogger,"sql = " << ss.str());
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
                quicknum = res->getString(1);
				LOG4CXX_WARN(gLogger,"quicknum = " << quicknum);
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }

    return strlen(quicknum.c_str()) > 1;
}
//绑定小号
bool bindshort(const string& acctname,string& bindnum)
{
	sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;
    string flag = "-1";

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }

    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call bind_shortnum("<< acctname << "," << bindnum << ")";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());
		LOG4CXX_WARN(gLogger,"sql = " << ss.str());
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
				flag = res->getString(1);
                //acctname = res->getString(1);
				LOG4CXX_WARN(gLogger,"bind_shortnum = " << res->getString(1));
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }
	//1 ok 
	return strcmp(flag.c_str(), "1") == 0;

}
//短号转计费号
bool shorttoacctname(const string& bindnum,string& acctname)
{
    sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;
    acctname = "0";

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }

    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call acct_shrottoacct(" << bindnum << ")";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());
		LOG4CXX_WARN(gLogger,"sql = " << ss.str());
        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
                acctname = res->getString(1);
				LOG4CXX_WARN(gLogger,"acctname = " << acctname);
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }

    return strlen(acctname.c_str()) > 1;
}



bool getbalance(const string& acc, const string& pwd, const string& caller, int type, double& fbalance)
{
    sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;
    fbalance = -1.0;

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }

    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call acct_balance(" << acc << "," << pwd << "," << caller << "," << type << ")";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());

        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
                fbalance = res->getDouble(1);
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }

    return fbalance > 0;
}
bool charged(const string& caller, const string& acct, const string& card, const string& pwd, float& card_value, float& fbalance)
{
    sql::Connection* pConn = dbs.GetDBC();
    bool bConnErr = false;
    int bRet = -1;

    if (!pConn)
    {
        LOG4CXX_WARN(gLogger, "Get Database Connect failed");
        return false;
    }

    try
    {
        std::auto_ptr< sql::ResultSet > res;
        stringstream ss;
        ss << "call acct_charged('" << caller << "','" << acct << "','" << card << "','" << pwd << "')";
        std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
        stmt->execute(ss.str());

        do
        {
            res.reset(stmt->getResultSet());

            while ((res.get() != NULL) && res->next())
            {
                bRet = res->getInt(1);

                if (bRet == 0)
                {
                    card_value = res->getDouble(2);
                    fbalance = res->getDouble(3);
                }

                LOG4CXX_DEBUG(gLogger, "sql=<" << ss.str() << "> ret=<" << bRet << "> card_value=<" << card_value << "> balance=<" << fbalance << ">");
            }
        }
        while (stmt->getMoreResults());
    }
    catch (sql::SQLException &e)
    {
        if (e.getErrorCode() == 2006)
        {
            bConnErr = true;
            delete pConn;
        }

        LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
                     << " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
    }
    catch (std::runtime_error &e)
    {
        LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
                     << "\r\bERROR: " << e.what() );
    }

    if (!bConnErr)
    {
        dbs.ReleaseDBC(pConn);
    }

    return bRet == 0;
}




bool auth_voip(const string& acc, const string& caller,string& authcode)
{
	sql::Connection* pConn = dbs.GetDBC();
	bool bConnErr = false;
	bool bRet=true;

	if (!pConn)
	{
		LOG4CXX_WARN(gLogger, "Get Database Connect failed");
		return false;
	}

	try
	{
		std::auto_ptr< sql::ResultSet > res;
		stringstream ss;
		ss << "call auth_voipcaller(\"" << acc << "\",\"" << caller << "\",\"" << (authcode.empty()?"":authcode) << "\")";
		std::auto_ptr<sql::Statement> stmt(pConn->createStatement());
		stmt->execute(ss.str());
		do
		{
			res.reset(stmt->getResultSet());
			while ((res.get() != NULL) && res->next())
			{		
				bRet = (res->getInt(1)>0);
			}
		}
		while (stmt->getMoreResults());
	}
	catch (sql::SQLException &e)
	{
		if (e.getErrorCode() == 2006)
		{
			bConnErr = true;
			delete pConn;
		}
		
		LOG4CXX_WARN(gLogger, "ERROR: SQLException in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__ << "\r\nERROR: " << e.what()
			<< " (MySQL error code: " << e.getErrorCode() << ", SQLState: " << e.getSQLState() << ")");
		bRet=false;
	}
	catch (std::runtime_error &e)
	{
		LOG4CXX_WARN(gLogger, "ERROR: runtime_error in " << __FILE__ << " (" << __func__ << ") on line " << __LINE__
			<< "\r\bERROR: " << e.what() );
		bRet=false;
	}
        if (!bConnErr)    
        {        
               dbs.ReleaseDBC(pConn);    
        }
        return bRet;
}
